home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1992 by Panagiotis Tsirigotis
- * All rights reserved. The file named COPYRIGHT specifies the terms
- * and conditions for redistribution.
- */
-
- static char RCSid[] = "$Id: init.c,v 5.1 1992/11/01 00:01:21 panos Exp $" ;
-
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <syslog.h>
- #include <fcntl.h>
-
- #include "sio.h"
- #include "str.h"
- #include "pset.h"
- #include "xlog.h"
-
- #include "options.h"
-
- #include "defs.h"
- #include "config.h"
- #include "state.h"
- #include "conf.h"
-
-
- struct module
- {
- char *name ;
- status_e (*initializer)() ;
- } ;
-
-
- status_e msg_init() ;
- status_e service_init() ;
- status_e server_init() ;
- status_e conn_init() ;
- status_e addrlist_init() ;
- status_e interval_init() ;
- status_e signal_init() ;
- status_e initenv() ;
-
- static struct module program_modules[] =
- {
- { "service", svc_init },
- { "server", server_init },
- { "connection", conn_init },
- { "addrlist", addrlist_init },
- { "time intervals", interval_init },
- { "signal", signal_init },
- { "environment", initenv },
- { CHAR_NULL }
- } ;
-
-
- /*
- * Keep open descriptors 0..DONT_CLOSE
- */
- #define DONT_CLOSE 2
-
- extern int sys_nerr;
- extern char *sys_errlist[];
- extern int errno;
-
- void msg() ;
-
- void exit() ;
-
-
- /*
- * Perform all necessary initializations
- */
- void init_daemon( argc, argv )
- int argc ;
- char *argv[] ;
- {
- void init_common(), init_no_debug(), init_rw_state() ;
-
- (void) opt_recognize( argc, argv ) ;
-
- init_common( argc, argv ) ;
-
- if ( ! debug.on )
- init_no_debug() ;
-
- init_rw_state() ;
- }
-
-
- /*
- * This function is invoked when a system call fails during initialization.
- * A message is printed to stderr, and the program is terminated
- */
- PRIVATE void syscall_failed( call )
- char *call ;
- {
- char errno_buf[ 40 ] ;
- char *err ;
-
- if ( errno < sys_nerr )
- err = sys_errlist[ errno ] ;
- else
- err = strx_sprint( errno_buf, sizeof(errno_buf), "errno = %d", errno ) ;
-
- Sprint( 2, "%s: %s failed: %s\n", program_name, call, err ) ;
- exit( 1 ) ;
- }
-
-
- /*
- * Initializations performed regardless of debugging
- */
- PRIVATE void init_common( argc, argv )
- int argc ;
- char *argv[] ;
- {
- int fd ;
- struct rlimit rl ;
- char *func = "init_common" ;
-
- #ifdef RLIMIT_NOFILE
- /*
- * Set the soft file descriptor limit to the hard limit.
- * We do this here because getdtablesize() returns the soft limit
- */
- ps.ros.orig_max_descriptors = getdtablesize() ;
- if ( getrlimit( RLIMIT_NOFILE, &rl ) != -1 )
- {
- rl.rlim_cur = rl.rlim_max ;
- (void) setrlimit( RLIMIT_NOFILE, &rl ) ;
- }
- if ( Smorefds() == SIO_ERR )
- syscall_failed( "malloc" ) ;
- #endif /* RLIMIT_NOFILE */
-
- debug.on = d_option ;
-
- ps.ros.Argv = argv ;
- ps.ros.Argc = argc ;
- ps.ros.config_file = f_option ? f_option_arg : DEFAULT_CONFIG_FILE ;
- ps.ros.max_descriptors = getdtablesize() ;
- ps.ros.is_superuser = ( geteuid() == 0 ) ;
- if ( limit_option )
- ps.ros.process_limit = limit_option_arg ;
- ps.ros.loop_rate = ( loop_option ) ? loop_option_arg : DEFAULT_LOOP_RATE ;
- ps.rws.descriptors_free = ps.ros.max_descriptors - DESCRIPTORS_RESERVED ;
-
- for ( fd = DONT_CLOSE+1 ; fd < ps.ros.max_descriptors ; fd++ )
- (void) close( fd ) ;
-
- xlog_parms( XLOG_SYSLOG, program_name, LOG_PID + LOG_NOWAIT, LOG_DAEMON ) ;
-
- /*
- * The remaining functions must be called AFTER we determine
- * if debugging is enabled because their behavior depends on it
- */
- if ( msg_init() == FAILED )
- syscall_failed( "msg_init" ) ;
-
- {
- struct module *mp ;
-
- for ( mp = program_modules ; mp->name ; mp++ )
- if ( (*mp->initializer)() == FAILED )
- {
- msg( LOG_CRIT, func,
- "Initialization of %s facility failed. Exiting...", mp->name ) ;
- exit( 1 ) ;
- }
- }
- (void) umask( 0 ) ;
- }
-
-
- /*
- * Initializations performed when debugging is not enabled
- */
- PRIVATE void init_no_debug()
- {
- int fd ;
- int root_fd ;
- int tries ;
- pid_t pid ;
- char *func = "init_no_debug" ;
- struct name_value *nv_find_value() ;
- void no_control_tty() ;
-
- /*
- * Reserve descriptors 0, 1, 2.
- * We need to do this because when we start a server we
- * dup the socket connection to 0, 1, 2. If those descriptors are
- * not reserved, it is possible that they are assigned to syslog
- * and we want to avoid that.
- */
- if ( ( root_fd = open( "/", O_RDONLY ) ) == -1 )
- syscall_failed( "open" ) ;
-
- for ( fd = 0 ; fd <= DONT_CLOSE ; fd++ )
- if ( root_fd != fd && dup2( root_fd, fd ) == -1 )
- syscall_failed( "dup2" ) ;
-
- if ( root_fd > DONT_CLOSE )
- (void) close( root_fd ) ;
-
- /*
- * First fork so that the parent will think we have exited
- */
- for ( tries = 0 ;; tries++ )
- {
- if ( tries == 5 )
- {
- msg( LOG_CRIT, func, "fork: %m. Exiting..." ) ;
- exit( 0 ) ;
- }
- pid = fork() ;
- if ( pid == -1 )
- {
- sleep( 1 ) ; /* wait for a second */
- continue ; /* and then retry */
- }
- if ( pid == 0 )
- break ;
- else
- {
- sleep( 3 ) ; /* give some time to the daemon to initialize */
- if ( pid_option )
- Sprint( 2, "%d\n", pid ) ;
- exit( 0 ) ;
- }
- }
- no_control_tty() ;
- }
-
-
- /*
- * Initialize all services
- *
- * This function is either successful in starting some services
- * or it terminates the program.
- */
- void init_services()
- {
- struct configuration conf ;
- char *func = "init_services" ;
- unsigned start_services() ;
- status_e get_configuration() ;
- void include_special_services() ;
-
- if ( get_configuration( &conf ) == FAILED )
- {
- msg( LOG_CRIT, func, "couldn't get configuration. Exiting..." ) ;
- exit( 1 ) ;
- }
-
- SVC_HOLD( conf.defaults ) ;
- ps.rws.cs.defaults = conf.defaults ;
-
- (void) start_services( conf.services ) ;
-
- /*
- * The number of available/active services is kept by the service functions
- */
- if ( ps.rws.available_services == 0 )
- {
- msg( LOG_CRIT, func, "no services. Exiting..." ) ;
- exit( 1 ) ;
- }
-
- include_special_services() ;
- }
-
-
- /*
- * Create allocators and tables
- */
- PRIVATE void init_rw_state()
- {
- pset_h new_table() ;
-
- ps.rws.servers = new_table( 0 ) ;
- ps.rws.retries = new_table( 0 ) ;
- ps.rws.services = new_table( 0 ) ;
-
- FD_ZERO( &ps.rws.socket_mask ) ;
- ps.rws.mask_max = 0 ;
-
- }
-
-
- PRIVATE pset_h new_table( size )
- unsigned size ;
- {
- char *func = "new_table" ;
- pset_h tab = pset_create( size, 0 ) ;
-
- if ( tab == NULL )
- {
- msg( LOG_CRIT, func, "Failed to create table" ) ;
- exit( 1 ) ;
- }
- return( tab ) ;
- }
-
-